package nioserver;

import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 分配器
 * 
 * 分配器的主要职责是负责监视 SelectionKey 队列之中已经被选取的 OP_READ 事件，如果队列中无任何事件，分配器线程处于中断状态，
 * 一旦有新的事件被注册到分配器中，分配器线程会被唤醒，去处理这个事件。
 * 为了说明 Reactor 模式，本例中，设计了只要有事件被注册，分配器就新建一个请求处理线程去读取数据这种简单的资源调度机制。
 * 在实际应用中，线程、数据库连接，内存等等都是资源，在有限的情况下，分配这些资源都会比这个模型复杂的多。
 * 
 * @author Xinz
 *
 */
public class NIODispatcher extends Thread {

	private static LinkedBlockingQueue<SelectionKey> queue = new LinkedBlockingQueue<SelectionKey>();
	
	@Override
	public void run() {
		for(;;) {
			try  {
				dispatch();
			}
			catch(IOException e) {
				e.printStackTrace();
			}
			catch(InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	
	public void dispatch() throws IOException, InterruptedException {
		synchronized(queue) {
			if(queue.size() <= 0) {
				queue.wait();
			}
			else {
				// 拿出队列中的第一个事件，创建一个新的任务处理程序
				SelectionKey key = queue.poll();
				new NIORequestHandler(key).start();
			}
		}
	}
	
	/**
	 * 注册新的事件，并唤醒当前线程
	 * @param key
	 */
	public void register(SelectionKey key) {
		synchronized(queue) {
			queue.add(key);
			queue.notify();
		}
	}
}
